package com.sunrise.xdoc.view.config;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

import com.sunrise.xdoc.entity.catalog.SanPham;
import com.sunrise.xdoc.entity.config.Ban;
import com.sunrise.xdoc.entity.order.ChiTietDonHang;
import com.sunrise.xdoc.entity.order.DonHang;
import com.sunrise.xdoc.utils.SunriseCollectionUtils;

/**
 * Chuyển bàn data. This class tight couple with {@link DanhSachBanKhuVuc}.
 * 
 * @author phphuc
 * 
 */
@ManagedBean
@SessionScoped
public class ChuyenBan implements Serializable {
	private static final long serialVersionUID = 405406155001523906L;

	@ManagedProperty(value = "#{danhSachBanKhuVuc}")
	private DanhSachBanKhuVuc danhSachBanKhuVuc;

	private Set<Ban> movedToBans = new HashSet<>();

	/**
	 * Đơn hàng nếu được gộp từ nhiều đơn hàng khác (chưa lưu xuống
	 * database)
	 */
	private DonHang donHangGopTam = new DonHang();

	public void onClickBan(Ban clickedBan) {
		Set<Ban> groupBans = danhSachBanKhuVuc.getGroupBans(clickedBan);
		if (movedToBans.contains(clickedBan)) {
			movedToBans.removeAll(groupBans);
		} else {
			movedToBans.addAll(groupBans);
		}

		gopBanTam();
	}

	private void gopBanTam() {
		DonHang selectedDH = danhSachBanKhuVuc.getBan2DonHang().get(
				danhSachBanKhuVuc.getSelectedBans().iterator().next());
		Set<DonHang> donHangs = findDonHangs(movedToBans);
		donHangs.add(selectedDH);
		setDonHangGopTam(gopDonHangs(SunriseCollectionUtils.clone(donHangs), movedToBans));

	}

	public DonHang gopDonHangs(Collection<DonHang> donHangs, Set<Ban> bans) {
		DonHang newDH = new DonHang();
		List<ChiTietDonHang> ctDHs = new ArrayList<>();
		for (DonHang dh : donHangs) {
			ctDHs.addAll(dh.getChiTietDonHangs());
		}
		ctDHs = new ArrayList<>(gopChiTietDHs(ctDHs, newDH));
		newDH.setChiTietDonHangs(ctDHs);
		newDH.getBans().addAll(bans);
		// TODO newDH.setGiamGia(giamGia)
		// TODO newDH.setMaNhanVienPhucVu(maNhanVienPhucVu)
		updateDonHangTheoChiTietDonHangs(newDH);
		return newDH;
	}

	private void updateDonHangTheoChiTietDonHangs(DonHang dh) {
		long tongGiaSP = 0L;
		for (ChiTietDonHang ctdh : dh.getChiTietDonHangs()) {
			tongGiaSP += ctdh.getSoLuong() * ctdh.getDonGia();
		}
		dh.setTongGiaSanPham(tongGiaSP);
	}

	private Collection<ChiTietDonHang> gopChiTietDHs(List<ChiTietDonHang> ctDHs, DonHang newDH) {
		Map<SanPham, ChiTietDonHang> sp2Ctdh = new HashMap<>();
		for (ChiTietDonHang ct : ctDHs) {
			ChiTietDonHang ctdh = sp2Ctdh.get(ct.getSanPham());
			if (ctdh == null || !ctdh.getSanPham().equals(ct.getSanPham())) {
				ChiTietDonHang newCtdh = new ChiTietDonHang();
				newCtdh.setDonGia(ct.getDonGia());
				newCtdh.setDonHang(newDH);
				newCtdh.setSanPham(ct.getSanPham());
				newCtdh.setSoLuong(ct.getSoLuong());
				sp2Ctdh.put(ct.getSanPham(), newCtdh);
			} else {
				ctdh.setSoLuong(ctdh.getSoLuong() + ct.getSoLuong());
				ctdh.setDonHang(newDH);
			}
		}
		return sp2Ctdh.values();
	}

	private Set<DonHang> findDonHangs(Set<Ban> movedToBans) {
		Set<DonHang> dhs = new HashSet<>();
		for (Ban b : movedToBans) {
			DonHang dh = danhSachBanKhuVuc.getBan2DonHang().get(b);
			if (dh != null) {
				dhs.add(dh);
			}
		}
		return dhs;
	}

	public void resetData() {
		movedToBans.clear();
	}

	public boolean isMovedToBan(Ban ban) {
		return movedToBans.contains(ban);
	}

	public String getMovedToBansLabel() {
		if (movedToBans.isEmpty()) {
			return "";
		}
		StringBuffer label = new StringBuffer();
		for (Ban b : movedToBans) {
			label.append(b.getName()).append(", ");
		}
		return label.substring(0, label.length() - 2);
	}

	public Set<Ban> getMovedToBans() {
		return movedToBans;
	}

	public boolean getCoTheChuyenBan() {
		return !movedToBans.isEmpty();
	}

	public DanhSachBanKhuVuc getDanhSachBanKhuVuc() {
		return danhSachBanKhuVuc;
	}

	public void setDanhSachBanKhuVuc(DanhSachBanKhuVuc danhSachBanKhuVuc) {
		this.danhSachBanKhuVuc = danhSachBanKhuVuc;
	}

	public DonHang getDonHangGopTam() {
		return donHangGopTam;
	}

	public void setDonHangGopTam(DonHang donHangGopTam) {
		this.donHangGopTam = donHangGopTam;
	}

}
